#include "sd_server.h"
#include "sd_global.h"
#include "sd_memory.h"
#include "sd_ttree.h"
#include "sd_transaction.h"
#include "sd_script.h"
#include <pthread.h>

extern void ExitAll();
extern void PrintIdxState(IdxState* idx, FILE* fp);

int unit_test1()
{
	IdxState* idx1;
	Key k1;
	Record record;
	int i;
	char *a_key = "a_key";
	FILE* fp;

	k1.type = KEYTYPE_SHORT;
	k1.keyval.shortkey = 100;
	memcpy(record.payload, a_key, strlen(a_key)+1);

	fp = fopen("unit_test1.txt", "w");

	create(KEYTYPE_SHORT, "test_1");
	openIndex("test_1", &idx1);
	for (i=0;i<64;i+=2)
	{
		k1.keyval.shortkey = i;
		insertRecord(idx1, NULL, &k1, record.payload);
		PrintIdxState(idx1, fp);
		fflush(fp);
		fprintf(fp,"=============================================================\n");
	}
	for (i=1;i<64;i+=2)
	{
		k1.keyval.shortkey = i;
		insertRecord(idx1, NULL, &k1, record.payload);
		PrintIdxState(idx1, fp);
		fflush(fp);
		fprintf(fp,"=============================================================\n");
	}
	closeIndex(idx1);
	fclose(fp);
	return 0;
}


int unit_test3()
{
	IdxState* idx1;
	Key k1;
	Record record;
	int i;
	char *a_key = "a_key";
	FILE* fp;

	k1.type = KEYTYPE_SHORT;
	k1.keyval.shortkey = 100;
	memcpy(record.payload, a_key, strlen(a_key)+1);

	fp = fopen("unit_test3.txt", "w");

	create(KEYTYPE_SHORT, "test_3");
	openIndex("test_3", &idx1);
	for (i=32;i>=0;i--)
	{
		k1.keyval.shortkey = i;
		insertRecord(idx1, NULL, &k1, record.payload);
		PrintIdxState(idx1, fp);
		fflush(fp);
		fprintf(fp,"=============================================================\n");
	}
	fprintf(fp,"=============================================================\n\n\n");
	
	for (i=0;i<32;i+=2)
	{
		record.key.keyval.shortkey = i;
		record.payload[0]=0;
		deleteRecord(idx1, NULL, &record);
		PrintIdxState(idx1, fp);
		fflush(fp);
		fprintf(fp,"=============================================================\n");
	}
	for (i=1;i<32;i+=2)
	{
		record.key.keyval.shortkey = i;
		record.payload[0]=0;
		deleteRecord(idx1, NULL, &record);
		PrintIdxState(idx1, fp);
		fflush(fp);
		fprintf(fp,"=============================================================\n");
	}
	closeIndex(idx1);
	fclose(fp);
	return 0;
}

int unit_test4()
{
	Key k1;
	Record record;
	int i;
	char *a_key = "a_key";
	FILE* fp;
	sd_TTree* tree;

	k1.type = KEYTYPE_SHORT;
	k1.keyval.shortkey = 100;
	memcpy(record.payload, a_key, strlen(a_key)+1);

	fp = fopen("unit_test4.txt", "w");

	sd_TTreeCreate(&tree, 4, sd_KeyShortCompare);

	for (i=32;i>=0;i--)
	{
		k1.keyval.shortkey = i;
		record.key.keyval.shortkey = i;
		record.key.type = KEYTYPE_SHORT;
		/*bug  unable to transform automatically  from Record to sd_Record*/
		sd_TTreeInsert(tree, (sd_Record*)&record);
		sd_TTreePrint(tree, fp);
		fflush(fp);
		fprintf(fp,"=============================================================\n");
	}
	fprintf(fp,"=============================================================\n\n\n");
	for (i=0;i<=32;i++)
	{
		k1.keyval.shortkey = i;
		record.key.keyval.shortkey = i;
		record.key.type = KEYTYPE_SHORT;
		record.payload[0] = 0;
		sd_TTreeDelete(tree,(sd_Record*)&record);
		sd_TTreePrint(tree, fp);
		fflush(fp);
		fprintf(fp,"=============================================================\n");
	}
	fprintf(fp,"=============================================================\n\n\n");
	sd_TTreeFree(tree);
	fclose(fp);
	return 0;
}

void* test_pthread(void* arg)
{
	pthread_t  tid;
    int* flag = (int*)arg;
	pthread_rwlock_t lock;

	pthread_rwlock_init(&lock, NULL);
	pthread_rwlock_wrlock(&lock);
	pthread_rwlock_unlock(&lock);
	pthread_rwlock_destroy(&lock);
	tid = pthread_self();
	printf("tid = %d\n",tid);
	*flag = 1;
	return NULL;
}

int unit_test5()
{
	pthread_t tid;
	int err;
	int flag = 0;

	err = pthread_create(&tid, NULL, test_pthread, &flag);
	if (err != 0)
	{
		SD_ASSERT(false);
		return -1;
	}
	while(flag == 0) {};
	return 0;
}

int unit_test2()
{
	IdxState* idx1;
	Key k1;
	Record record;
	int i;
	char *a_key = "a_key";
	FILE* fp;

	k1.type = KEYTYPE_SHORT;
	k1.keyval.shortkey = 100;
	memcpy(record.payload, a_key, strlen(a_key)+1);

	fp = fopen("unit_test2.txt", "w");

	create(KEYTYPE_SHORT, "test_2");
	openIndex("test_2", &idx1);
	for (i=10;i>=0;i--)
	{
		k1.keyval.shortkey = i;
		insertRecord(idx1, NULL, &k1, record.payload);
		PrintIdxState(idx1, fp);
		fflush(fp);
		fprintf(fp,"=============================================================\n");
	}
	for (i=30;i>=20;i--)
	{
		k1.keyval.shortkey = i;
		insertRecord(idx1, NULL, &k1, record.payload);
		PrintIdxState(idx1, fp);
		fflush(fp);
		fprintf(fp,"=============================================================\n");
	}
	for (i=20;i>=10;i--)
	{
		k1.keyval.shortkey = i;
		insertRecord(idx1, NULL, &k1, record.payload);
		PrintIdxState(idx1, fp);
		fflush(fp);
		fprintf(fp,"=============================================================\n");
	}
	closeIndex(idx1);
	fclose(fp);
	return 0;
}
int unit_test6()
{
	IdxState* idx1;
	TxnState* txn;
	Key k1;
	Record record;
	int i;
	char *a_key = "a_key";
	FILE* fp;

	k1.type = KEYTYPE_SHORT;
	k1.keyval.shortkey = 100;
	memcpy(record.payload, a_key, strlen(a_key)+1);

	fp = fopen("unit_test6.txt", "w");

	create(KEYTYPE_SHORT, "test_6");
	openIndex("test_6", &idx1);

	/* Transaction 1 */
	fprintf(fp,"Begin Transaction!\n");
	fprintf(fp,"=============================================================\n");
	beginTransaction(&txn);
	for (i=10;i>=0;i--)
	{
		k1.keyval.shortkey = i;
		insertRecord(idx1, txn, &k1, record.payload);
		PrintIdxState(idx1, fp);
		fflush(fp);
		fprintf(fp,"=============================================================\n");
	}
	for (i=30;i>=20;i--)
	{
		k1.keyval.shortkey = i;
		insertRecord(idx1, txn, &k1, record.payload);
		PrintIdxState(idx1, fp);
		fflush(fp);
		fprintf(fp,"=============================================================\n");
	}
	for (i=20;i>=10;i--)
	{
		k1.keyval.shortkey = i;
		insertRecord(idx1, txn, &k1, record.payload);
		PrintIdxState(idx1, fp);
		fflush(fp);
		fprintf(fp,"=============================================================\n");
	}
	fprintf(fp,"Commit Transaction!\n\n\n");
	fprintf(fp,"=============================================================\n");

	PrintIdxState(idx1, fp);

	commitTransaction(txn);
   
	fprintf(fp,"=============================================================\n\n\n");


	/* Transaction 2 */
	fprintf(fp,"Begin Transaction!\n");
	fprintf(fp,"=============================================================\n");
	beginTransaction(&txn);
	for (i=0;i<32;i++)
	{
		record.key.keyval.shortkey = i;
		record.payload[0]=0;
		deleteRecord(idx1, txn, &record);
		PrintIdxState(idx1, fp);
		fflush(fp);
		fprintf(fp,"=============================================================\n");
	}
	fprintf(fp,"Abort Transaction!\n\n\n");
	fprintf(fp,"=============================================================\n");
	SD_SET_LOGFILE(fp);
	abortTransaction(txn);
	PrintIdxState(idx1, fp);
	fprintf(fp,"=============================================================\n");

	closeIndex(idx1);
	fclose(fp);
	return 0;
}

int unit_test7(int argc, char* argv[])
{
#ifdef _DEBUG
	char* debugArgv[]={"contest.exe", "script_init.txt","script_0.txt", "script_1.txt"};
	int debugArgc = 4;
	argc = debugArgc;
	argv = debugArgv;
#endif
	sd_scriptRun(argc, argv);
	return 0;
}

//int main(int argc, char* argv[])
//{
//	sd_MemoryInit();
//	printf("Welcome to our database!\n");
//	unit_test1();
//	unit_test2();
//	unit_test3();
//	unit_test4();
//	unit_test5();
//	unit_test6();
//	//unit_test7(argc, argv);
//	ExitAll();
//	sd_MemoryCheck();
//	sd_MemoryExit();
//	return 0;
//}

